home *** CD-ROM | disk | FTP | other *** search
/ World of Education / World of Education.iso / world_x / xcoral16.zip / PAGE.C < prev    next >
C/C++ Source or Header  |  1993-01-15  |  21KB  |  948 lines

  1. /*
  2. ** Copyright 1989, 1992 by Lionel Fournigault
  3. **
  4. ** Permission to use, copy, and distribute for non-commercial purposes,
  5. ** is hereby granted without fee, providing that the above copyright
  6. ** notice appear in all copies and that both the copyright notice and this
  7. ** permission notice appear in supporting documentation.
  8. ** The software may be modified for your own purposes, but modified versions
  9. ** may not be distributed.
  10. ** This software is provided "as is" without any expressed or implied warranty.
  11. **
  12. **
  13. */
  14.  
  15. #include <X11/Xlib.h>
  16. #include <X11/Xutil.h>
  17. #include <stdio.h>
  18. #include <sys/types.h>
  19. #include <sys/time.h>
  20.  
  21. #include "buffer.h"
  22. #include "text.h"
  23. #include "scroll.h"
  24.  
  25. extern Display *dpy;
  26. static int DrawLineOfText ();
  27. static void ScrollUpFewLines ();
  28. static void ScrollDownFewLines ();
  29. static void ShiftLinesTable ();
  30.  
  31. /*
  32. **    Function name : FirstPage
  33. **
  34. **    Description : Affichage de la premiere page du buffer courant.
  35. **
  36. **    Input : Le text courant.
  37. **    Ouput :
  38. */
  39. void FirstPage ( text )
  40.     Text *text;
  41. {
  42.     text -> sl = 0;
  43.     HoleToLeft ( text -> buf );
  44.     text -> n1 = 0;
  45.     text -> n2 = text -> lines_in_page - 1;
  46. #ifdef DEBUG
  47.     (void) fprintf ( stderr,"ht = %d\n", text -> height );
  48. #endif
  49.     SetAndDisplayPage ( text );
  50.  
  51.     if ( text -> stat & MESSAGE ) {
  52.                         DisplayMessage ( text -> mwin, "  " );
  53.         MCLEAR ( text -> stat, MESSAGE );
  54.     }
  55.  
  56.     (void) MoveScrollBar ( dpy, text -> swin, FIRST, 0 );
  57.     text -> no_current_line = 1;
  58.  
  59.            MSET ( text -> stat, FIRSTPAGE );
  60.     MCLEAR ( text -> stat, LASTPAGE );
  61.  
  62. #ifdef DEBUG
  63.     (void) fprintf ( stderr, "cur_line = %d n1 = %d n2 = %d\n",
  64.          text -> no_current_line, text -> n1, text -> n2 );
  65. #endif DEBUG
  66. }
  67.  
  68.  
  69. /*
  70. **    Function name : ClearPage
  71. **
  72. **    Description : Comme son nom l'indique.
  73. **
  74. **    Input : Le text courant.
  75. **    Ouput :
  76. */
  77. void ClearPage ( text )
  78.     Text *text;
  79. {
  80.     XClearArea ( dpy, text -> window,
  81.         MARGE, MARGE, text -> width - ( 2 * MARGE ),
  82.         text -> height - ( 2 * MARGE ), False );
  83. }
  84.  
  85.  
  86. /*
  87. **    Function name : ClipOn
  88. **
  89. **    Description : Met le clip a partir de la ligne no n
  90. **        de la page courante.
  91. **        La ligne n n'est pas touchee par le clip.
  92. **
  93. **    Input : Le text courant, no de ligne.
  94. **    Ouput :
  95. */
  96. void ClipOn ( text, line )
  97.     Text *text;
  98.     register int line;
  99. {
  100.     XRectangle rect [1];
  101.  
  102.     rect [0].x = MARGE;
  103.     rect [0].width = text -> width - ( 2 * MARGE );
  104.  
  105.     if ( line <= 1 ) {
  106.            rect [0].y = MARGE;
  107.            rect [0].height = text -> height - ( 2 * MARGE );
  108.     }
  109.     else {
  110.            rect [0].y = MARGE + (line  * text -> font_height);
  111.                   rect [0].height = text -> height - ( 2 * MARGE )
  112.          - (line * text -> font_height );
  113.     }
  114.  
  115.     XSetClipRectangles ( dpy, text -> Cgc, 0, 0, rect, 1, False );
  116. }
  117.  
  118.  
  119. /*
  120. **    Function name : ClipOff
  121. **
  122. **    Description : Remet la zone de clip par defaut.
  123. **
  124. **    Input : Le text courant.
  125. **    Ouput :
  126. */
  127. void ClipOff ( text )
  128.     Text *text;
  129. {
  130.     XSetClipMask ( dpy, text -> Cgc, None );
  131. }
  132.  
  133.  
  134. /*
  135. **    Function name : ExposePage
  136. **
  137. **    Description : Exposition de la page courante.
  138. **        Deux cas possibles : 
  139. **            -Configure ( Resize )
  140. **            -Expose-Region
  141. **
  142. **    Input : La region exposee, le text courant.
  143. **    Ouput :
  144. */
  145. void ExposePage ( r, text )
  146.     Region r;
  147.     Text *text;
  148. {
  149.     XRectangle rect [1];
  150.     Region inter, region;
  151.  
  152.     if (  TextInBuf ( text ) != True )
  153.         return;
  154.  
  155.     /* Configure */
  156.     if ( text -> n1 > text -> lines_in_page - 1 ) {
  157.  
  158.            text -> n1 = text -> lines_in_page - 1;
  159.            text -> n2 = 0;
  160.            SetAndDisplayPage ( text );
  161.            (void) MoveScrollBar ( dpy, text -> swin, CURRENT, text -> no_current_line - 1 - text -> n1 );
  162.            return;
  163.     }
  164.  
  165.     /* Expose */
  166.     region = XCreateRegion ();
  167.     inter = XCreateRegion ();
  168.  
  169.     rect [0].x = MARGE;
  170.     rect [0].y = MARGE;
  171.     rect [0].width = text -> width - ( 2 * MARGE );
  172.     rect [0].height = text -> height - ( 2 * MARGE );
  173.  
  174.     XUnionRectWithRegion ( rect, region, region );
  175.  
  176.     XIntersectRegion ( r, region, inter );
  177.     XSetRegion ( dpy, text -> Cgc, inter );
  178.  
  179.     (void) SetLinesTable ( text );
  180.     RefreshPage ( text );
  181.  
  182.     XDestroyRegion ( inter );
  183.     XDestroyRegion ( region );
  184. }
  185.  
  186.  
  187. /*
  188. **    Function name : SetLinesTable
  189. **
  190. **    Description : Mise a jour de la table des lignes
  191. **        pour la page courante.
  192. **
  193. **    Input : Le text courant.
  194. **    Ouput :
  195. */
  196. void SetLinesTable ( text )
  197.     Text *text;
  198. {
  199.     register int line, n = 0, wl = 1;
  200.     register char *s;
  201.     char *HscrollString ();
  202.     int len;
  203.  
  204.     /*
  205.      * Si ya rien dans le buffer, il faut absolument
  206.      * virer le pointeur de la ligne courante car
  207.      * celui-ci est global a tous les buffers
  208.      * 
  209.      */
  210.     if (  TextInBuf ( text ) != True ) {
  211.         text -> page.sline [ text -> n1 + 1 ] = (char *) 0;
  212.         return;
  213.     }
  214.  
  215.  
  216.        for ( line = text -> n1; line > 0 ; line-- ) {
  217.         s = ( char * ) GetBackwardLine ( text -> buf, -line, &len );
  218.         if ( s ) {
  219.                 if ( text -> sl )
  220.                    s = HscrollString ( s, text -> sl, text -> tab_width ); 
  221.             text -> page.sline [ wl ] = s;
  222.         }
  223.         else {
  224. #ifdef DEBUG
  225.         (void) fprintf ( stderr,"sline null wl = %d\n", wl );
  226. #endif DEBUG
  227.                text -> page.sline [ wl ] = ( char * ) 0;
  228.                n++;
  229.                continue;
  230.         }
  231.         wl++;
  232.     }
  233.     for ( line = 0; line < text -> n2 + 1 + n; line++ ) {
  234.         if ( line == 0 )
  235.             s = ( char * ) GetCurrentLine ( text -> buf, &len );
  236.         else
  237.             s = ( char * ) GetForwardLine ( text -> buf, line, &len );
  238.         if ( s ) {
  239.             if ( text -> sl )
  240.                 s = HscrollString ( s, text -> sl, text -> tab_width );
  241.             text -> page.sline [ wl ] = s;
  242.         }
  243.         else {
  244. #ifdef DEBUG
  245.         (void) fprintf ( stderr,"sline null wl = %d\n", wl );
  246. #endif DEBUG
  247.           text -> page.sline [ wl ] = ( char * ) 0;
  248.                        }
  249.         wl ++;
  250.     }
  251.     text -> n1 -= n;
  252.     text -> n2 += n;
  253. }
  254.  
  255.  
  256. /*
  257. **    Function name : SetCurrentLine
  258. **
  259. **    Description : Affiche la ligne courante.
  260. **
  261. **    Input : Le text courant.
  262. **    Ouput :
  263. */
  264. void SetCurrentLine ( text )
  265.     Text *text;
  266. {
  267.        register char *s;
  268.        int len;
  269.        register int line = text -> n1 + 1;
  270.        register int max = text -> width - ( 2 * MARGE );
  271.  
  272.        ClearLine ( text, line );
  273.        ClipOn ( text, 0 );
  274.  
  275.     s = ( char * ) GetCurrentLine ( text -> buf, &len ); 
  276.        
  277.        if ( s ) {
  278.               if ( text -> sl )
  279.                s = (char *) HscrollString ( s, text -> sl, text -> tab_width );
  280.           text -> page.sline [ line ] = s;
  281.  
  282.           text -> page.wline [ line ] =  DrawLineOfText ( text, line );
  283.  
  284.              if ( text -> page.wline [ line ] > max )
  285.                     text -> page.wline [ line ] = max;
  286.           
  287.        }
  288.        ClipOff ( text );
  289. }
  290.  
  291.  
  292. /*
  293. **    Function name : RefreshPage
  294. **
  295. **    Description : Affiche la page courante.
  296. **
  297. **    Input : Le text courant.
  298. **    Ouput :
  299. */
  300. void RefreshPage ( text )
  301.     Text *text;
  302. {
  303.     register int i = 1;
  304.     register int max = text -> width - ( 2 * MARGE );
  305.  
  306.     do {
  307.         ClearLine ( text, i );
  308.         if ( text -> page.sline [ i ] ) {
  309.             text -> page.wline [i] = DrawLineOfText ( text, i );
  310.             if ( text -> page.wline [ i ] > max )
  311.                 text -> page.wline [ i ] = max;
  312.         }
  313.         else
  314.             text -> page.wline [ i ] = 0;
  315.         i++;
  316.     } while ( i < text -> lines_in_page + 1);
  317. }
  318.  
  319.  
  320. /*
  321. **    Function name : ClearLine
  322. **
  323. **    Description : Efface la ligne i.
  324. **
  325. **    Input : Le text courant, le no de la ligne.
  326. **    Ouput :
  327. */
  328. void ClearLine ( text, i )
  329.     Text *text;
  330.     register int i;
  331. {
  332.        register int width;
  333.  
  334.        XSetForeground ( dpy, text -> Cgc, text -> bg );
  335.  
  336.        if ( (width = text -> page.wline [i]) != 0 ) {
  337.               XFillRectangle ( dpy, text -> window, text -> Cgc,
  338.              MARGE,
  339.                  MARGE + ( (i - 1) * text -> font_height ),
  340.              width + 1, text -> font_height + 1 );
  341.  
  342.               text -> cursor_stat = OFF;
  343.        }
  344.  
  345.        XSetForeground ( dpy, text -> Cgc, text -> fg );
  346. }
  347.  
  348.  
  349. /*
  350. **    Function name : DrawLineOfText
  351. **
  352. **    Description : Affiche la ligne i en
  353. **        tenant compte des tabs.
  354. **
  355. **    Input : Le text courant, le no de ligne.
  356. **    Ouput :
  357. */
  358. static int DrawLineOfText ( text, li )
  359.     Text *text;
  360.     register int li;
  361. {
  362.     register int n = 1;  /* Caracteres en cours de traitement    */
  363.     register char  *p, *s;
  364.     register int xx, width;
  365.  
  366.     register int sizetab = text -> tab_width * text -> char_width_ave;
  367.  
  368.     register int y = MARGE + text -> font -> max_bounds.ascent  
  369.                      + ( (li -1) * ( text -> font_height ));
  370.     register int x = MARGE;
  371.     register char *end_of_buf = BottomBuf ( text -> buf ); 
  372.     register char *top_of_buf = TopBuf ( text -> buf ); 
  373.     register int type = False;
  374.  
  375.     s = p = text -> page.sline [li];
  376.     if ( (p >= top_of_buf) && (p <= end_of_buf) ) 
  377.         type = True;
  378.  
  379.     while ( *p != '\n' ) {
  380.         if ( *p == 0 ) 
  381.                      break;
  382.         if ( (type == True) && (p > end_of_buf) )
  383.             (void) fprintf ( stderr, "Internal Error 1...\n" );
  384.         if ( *p == '\t' ) {
  385.             if ( n > 1 )
  386.                 XDrawImageString ( dpy, text -> window,
  387.                     text -> Cgc, x, y, s, n - 1 );
  388.             xx =  sizetab;
  389.  
  390.             width = XTextWidth ( text -> font, s, n - 1); 
  391.             while ( width >= xx )     
  392.  
  393.                 xx += sizetab;
  394.             x += xx;
  395.             p++;
  396.             n = 1;
  397.             if ( (type == True) && (p > end_of_buf) ) 
  398.                 break;
  399.             s = p;
  400.         }
  401.         else {
  402.             n++;
  403.             p++;
  404.             if ( (type == True) && (p > end_of_buf) ) 
  405.                 break;
  406.         }
  407.     }
  408.     XDrawImageString ( dpy, text -> window, text -> Cgc, x, y, s, n - 1 );
  409.     return ( x + XTextWidth ( text -> font, s, n - 1 ));
  410. }
  411.  
  412.  
  413. /*
  414. **    Function name : LastPage
  415. **
  416. **    Description : Affiche la derniere page du buffer courant.
  417. **
  418. **    Input : Le text courant.
  419. **    Ouput :
  420. */
  421. void LastPage ( text )
  422.     Text *text;
  423. {
  424.     Buf *buf;
  425.  
  426.     buf = text -> buf;
  427.     if ( text -> stat & LASTPAGE ) {
  428.            DisplayMessage ( text -> mwin, END_MESS );
  429.            MSET ( text -> stat, MESSAGE );
  430.            return;
  431.     }
  432.     HoleToRight ( buf );
  433.     text -> no_current_line = text -> lines_in_buf;
  434.     text -> n1 = text -> lines_in_page - 1;
  435.     text -> n2 = 0;
  436.  
  437.     SetAndDisplayPage ( text );
  438.     (void) MoveScrollBar ( dpy, text -> swin,
  439.         CURRENT, text -> no_current_line - text -> n1 - 1 );
  440.     DisplayMessage ( text -> mwin, " " );
  441.     MSET ( text -> stat, LASTPAGE );
  442.     MCLEAR ( text -> stat, FIRSTPAGE );
  443.     MCLEAR ( text -> stat, MESSAGE );
  444.  
  445. #ifdef DEBUG
  446.     (void) fprintf ( stderr, "cur_line = %d n1 = %d n2 = %d\n",
  447.          text -> no_current_line, text -> n1, text -> n2 );
  448. #endif DEBUG
  449. }
  450.  
  451.  
  452. /*
  453. **    Function name : PreviousPage
  454. **
  455. **    Description : Affiche la page precedente.
  456. **
  457. **    Input : Le text courant.
  458. **    Ouput :
  459. */
  460. void PreviousPage ( text )
  461.     Text *text;
  462. {
  463.     Buf *buf;
  464.     int len;
  465.  
  466.     buf = text -> buf;
  467.  
  468. #ifdef DEBUG
  469.     (void) fprintf ( stderr, "n1 = %d ncl = %d\n",
  470.         text -> n1, text -> no_current_line );
  471. #endif
  472.     if ( (text -> no_current_line == 1)
  473.         || (! GetBackwardLine ( buf, - ( text -> n1 + 1 ), &len ))) {
  474.         DisplayMessage ( text -> mwin, "zz top..." );
  475.         MSET ( text -> stat, MESSAGE );
  476.         MSET ( text -> stat, FIRSTPAGE );
  477.         return;
  478.     }
  479.  
  480.     if ( MoveToLine ( buf, - text -> n1 ) == -1 ) {
  481.         (void) fprintf ( stderr, "Move error\n" );
  482.         return;
  483.     }
  484.     text -> no_current_line -= text -> n1;
  485.     text -> n1 = text -> lines_in_page - 1;
  486.     text -> n2 = 0;
  487.  
  488.     SetAndDisplayPage ( text );
  489.  
  490.     if ( text -> no_current_line - text -> n1 == 1 )
  491.            (void) MoveScrollBar ( dpy, text -> swin, FIRST, 0 );
  492.     else
  493.            (void) MoveScrollBar ( dpy, text -> swin, PREVIOUS, 0 );
  494.  
  495.     DisplayMessage ( text -> mwin, " " );
  496.     MCLEAR ( text -> stat, MESSAGE );
  497.     MCLEAR ( text -> stat, FIRSTPAGE );
  498.     MCLEAR ( text -> stat, LASTPAGE );
  499.  
  500. #ifdef DEBUG
  501.     (void) fprintf ( stderr, "cur_line = %d n1 = %d n2 = %d\n",
  502.          text -> no_current_line, text -> n1, text -> n2 );
  503. #endif DEBUG
  504.  
  505. }
  506.  
  507.  
  508. /*
  509. **    Function name : NextPage
  510. **
  511. **    Description : Affiche la page suivante.
  512. **
  513. **    Input : Le text courant.
  514. **    Ouput :
  515. */
  516. void NextPage ( text )
  517.     Text *text;
  518. {
  519.     Buf *buf;
  520.  
  521.     buf = text -> buf;
  522.  
  523. #ifdef DEBUG
  524.     (void) fprintf ( stderr, "n2 = %d\n", text -> n2 );
  525. #endif
  526.     if ( text -> stat & LASTPAGE ) {
  527.         DisplayMessage ( text -> mwin, END_MESS );
  528.         MSET ( text -> stat, MESSAGE );
  529.         return;
  530.     }
  531.  
  532.     if ( MoveToLine ( buf, text -> n2 ) == -1 ) { 
  533.         DisplayMessage ( text -> mwin, END_MESS );
  534.         MSET ( text -> stat, LASTPAGE );
  535.         MSET ( text -> stat, MESSAGE );
  536.         
  537.         return;
  538.     }
  539.  
  540.     text -> no_current_line += text -> n2;
  541.     text -> n1 = 0;
  542.     text -> n2 = text -> lines_in_page - 1;
  543.  
  544.     SetAndDisplayPage ( text );
  545.  
  546.     (void) MoveScrollBar ( dpy, text -> swin, NEXT, 0 );
  547.  
  548.     DisplayMessage ( text -> mwin, " " );
  549.     MCLEAR ( text -> stat, MESSAGE );
  550.     MCLEAR ( text -> stat, FIRSTPAGE );
  551.     MCLEAR ( text -> stat, LASTPAGE );
  552.  
  553. #ifdef DEBUG
  554.     (void) fprintf ( stderr, "cur_line = %d n1 = %d n2 = %d\n",
  555.          text -> no_current_line, text -> n1, text -> n2 );
  556. #endif DEBUG
  557. }
  558.  
  559.  
  560. /*
  561. **    Function name : GotoEnd
  562. **
  563. **    Description : Va a la fin du buffer.
  564. **
  565. **    Input : Le text courant.
  566. **    Ouput :
  567. */
  568. void GotoEnd ( text )
  569.     Text *text;
  570. {
  571.     HoleToRight ( text -> buf );
  572.     GotoLineNumber ( text, text -> lines_in_buf );
  573. }
  574.  
  575.  
  576. /*
  577. **    Function name : CurrentLineToTop
  578. **
  579. **    Description : Met la ligne courante au debut de la
  580. **        page.
  581. **
  582. **    Input : Le text courant.
  583. **    Ouput :
  584. */
  585. void CurrentLineToTop ( text )
  586.     Text *text;
  587. {
  588.         register int n;
  589.  
  590.         text -> n1 = 0;
  591.     text -> n2 = text -> lines_in_page - 1;
  592.  
  593.     SetAndDisplayPage ( text );
  594.     
  595.     n = text -> no_current_line - text -> n1 - 1;
  596.  
  597.     if ( n > NULL )
  598.         (void) MoveScrollBar ( dpy, text -> swin, CURRENT, n );
  599.     else
  600.         (void) MoveScrollBar ( dpy, text -> swin, FIRST, 0 );
  601. }
  602.  
  603.  
  604. /*
  605. **    Function name : GotoLineNumber
  606. **
  607. **    Description : Va a la ligne n.
  608. **
  609. **    Input : Le text courant, le no de ligne.
  610. **    Ouput :
  611. */
  612. void GotoLineNumber ( text, n )
  613.     Text *text;
  614.     register int n;
  615. {
  616.        if ( n < 1 ) return;
  617.        if ( n > text -> lines_in_buf ) 
  618.               n = text -> lines_in_buf;
  619.  
  620.        text -> sl = 0;
  621.        (void) MoveToLine ( text -> buf, n - text -> no_current_line );
  622.  
  623.        text -> no_current_line += ( n - text -> no_current_line );
  624. }
  625.  
  626.  
  627. /*
  628. **    Function name : ScrollNline
  629. **
  630. **    Description : Scroll n lignes de texte.
  631. **        Vers le debut ou la fin du buffer suivant
  632. **        le signe de n.
  633. **
  634. **    Input : Le nombre de ligne a scroller, le text courant.
  635. **    Ouput :
  636. */
  637. void ScrollNLine ( n, text )
  638.     register int n;
  639.     Text *text;
  640. {
  641.     Buf *buf;
  642. #define PAS 5
  643.  
  644.     buf = text -> buf;
  645.     if ( n < 0 ) {        /* On va vers le debut du buffer */
  646.             if ( -n > PAS ) {
  647.                (void) MoveToLine ( buf, n );
  648.                text -> no_current_line -= (-n);
  649.                if ( text -> no_current_line < text -> n1 ) {
  650.                       text -> n1 = text -> no_current_line - 1;
  651.                   text -> n2 = text -> lines_in_page - 1 - text -> n1;
  652.                }
  653.                SetAndDisplayPage ( text );
  654.         }
  655.         else
  656.                (void) ScrollUpFewLines ( text, n );
  657.      }
  658.      else {             /* On va vers ls fin du buffer */
  659.             if ( n > PAS ) {
  660.                register int tmp;
  661.                tmp = text -> lines_in_buf - text -> no_current_line;
  662.                if ( n <= tmp ) {
  663.                       (void) MoveToLine ( buf, n );
  664.                   text -> no_current_line += n;
  665.                }
  666.                else {
  667.                   (void) MoveToLine ( buf, tmp );
  668.                       text -> no_current_line += tmp;
  669.                   text -> n1 -= ( n - tmp );
  670.                   text -> n2 = text -> lines_in_page - 1 - text -> n1;
  671.                }
  672.                SetAndDisplayPage ( text );
  673.         }
  674.             else 
  675.                (void) ScrollDownFewLines ( text, n );
  676.     }
  677. }
  678.                
  679.  
  680. /*
  681. **    Function name : ScrollUpFewLines
  682. **
  683. **    Description : Scroll n lignes. Le texte defile
  684. **        vers le bas.
  685. **
  686. **    Input : Le text courant, le nombre de ligne a scroller.
  687. **    Ouput :
  688. */
  689. static void ScrollUpFewLines ( text, n )
  690.     Text *text;
  691.     register int n;
  692. {
  693.     register Buf *buf;
  694.     int len;
  695.  
  696.     buf = text -> buf;
  697. #ifdef DEBUG
  698.     (void) fprintf ( stderr, "Up n = %d\n", n );
  699. #endif
  700.     ClipOn ( text, NULL );
  701.         while ( n ) {
  702.            (void) ShiftLinesTable ( text, DOWN );
  703.            text -> page.sline [1] = 
  704.         GetBackwardLine ( buf, - ( text -> n1 + 1 ), &len ); 
  705.            RefreshPage ( text );
  706.  
  707.            if ( text -> n2 == NULL ) {
  708.                    (void) MoveToLine ( buf, -1 );
  709.                text -> no_current_line --;
  710.            }
  711.            else {
  712.                text -> n1 ++;
  713.                text -> n2 --;
  714.            }
  715.            n++;
  716.     }
  717.     ClipOff ( text );
  718.  
  719.     DisplayMessage ( text -> mwin, " " );
  720.     MCLEAR ( text -> stat, MESSAGE );
  721.     MCLEAR ( text -> stat, FIRSTPAGE );
  722.     MCLEAR ( text -> stat, LASTPAGE );
  723.  
  724. #ifdef DEBUG
  725.     (void) fprintf ( stderr, "cur_line = %d n1 = %d n2 = %d\n",
  726.          text -> no_current_line, text -> n1, text -> n2 );
  727. #endif DEBUG
  728. }
  729.  
  730.  
  731. /*
  732. **    Function name : ScrollDownFewLines
  733. **
  734. **    Description : Scroll n ligne. Le texte defile vers
  735. **        le haut.
  736. **
  737. **    Input : Le text courant, le nombre de lignes a scroller.
  738. **    Ouput :
  739. */
  740. static void ScrollDownFewLines ( text, n )
  741.     Text *text;
  742.     register int n;
  743. {
  744.     register Buf *buf;
  745.     int len;
  746.  
  747.     buf = text -> buf;
  748. #ifdef DEBUG
  749.     (void) fprintf ( stderr, "Down n = %d\n", n );
  750. #endif
  751.     ClipOn ( text, NULL );
  752.         while ( n ) {
  753.            (void) ShiftLinesTable ( text, UP );
  754.            text -> page.sline [text -> lines_in_page] = 
  755.         GetForwardLine ( buf, text -> n2 + 1, &len );
  756.            RefreshPage ( text );
  757.  
  758.            if ( text -> n1 == NULL ) {
  759.                    (void) MoveToLine ( buf, 1 );
  760.                text -> no_current_line ++;
  761.            }
  762.            else {
  763.                   text -> n1 --;
  764.               text -> n2 ++;
  765.            }
  766.            n--;
  767.        }
  768.         ClipOff ( text );
  769.     DisplayMessage ( text -> mwin, " " );
  770.     MCLEAR ( text -> stat, MESSAGE );
  771.     MCLEAR ( text -> stat, FIRSTPAGE );
  772.     MCLEAR ( text -> stat, LASTPAGE );
  773.  
  774. #ifdef DEBUG
  775.     (void) fprintf ( stderr, "cur_line = %d n1 = %d n2 = %d\n",
  776.          text -> no_current_line, text -> n1, text -> n2 );
  777. #endif DEBUG
  778. }
  779.  
  780.  
  781. /*
  782. **    Function name : ShiftLinesTable
  783. **
  784. **    Description : Delalage des pointeurs de la table
  785. **        des lignes dans le cas d'un scroll.
  786. **
  787. **    Input : Le text courant, la direction du scroll.
  788. **    Ouput :
  789. */
  790. static void ShiftLinesTable ( text, dir )
  791.     Text *text;
  792.     register int dir;
  793. {
  794.        char  *save[256];
  795.        register int i = 1;
  796.        
  797.        do {
  798.               save [i] = text -> page.sline [i];
  799.           i++;
  800.        } while ( i < text -> lines_in_page + 1 );
  801.  
  802.        switch ( dir ) {
  803.        case UP: 
  804.           i = 1;
  805.           while ( i < text -> lines_in_page ) {
  806.                  text -> page.sline [i] = save [i+1];
  807.              i++;
  808.           }
  809.           break;
  810.        case DOWN:
  811.           i = 1;
  812.           while ( i < text -> lines_in_page ) {
  813.                  text -> page.sline [i+1] = save [i];
  814.              i++;
  815.           }
  816.           break;
  817.        }
  818. }
  819.  
  820.  
  821. /*
  822. **    Function name : CurrentLineToMiddle
  823. **
  824. **    Description : Met la ligne courante au milieu
  825. **        de la page.
  826. **
  827. **    Input : Le text courant.
  828. **    Ouput :
  829. */
  830. void CurrentLineToMiddle ( text )
  831.     Text *text;
  832. {
  833.     register int n;
  834.  
  835.     if ( text -> no_current_line >= ( text -> lines_in_page / 2 )) { 
  836.         text -> n1 = text -> lines_in_page / 2;
  837.         text -> n2 = text -> lines_in_page - text -> n1 - 1;
  838.     }
  839.     else {
  840.         text -> n1 = text -> no_current_line - 1;
  841.         text -> n2 = text -> lines_in_page - text -> n1 - 1;
  842.     }
  843.  
  844.     SetAndDisplayPage ( text );
  845.  
  846.     n = text -> no_current_line - text -> n1 - 1;
  847.  
  848. #ifdef DEBUG
  849.     (void) fprintf ( stderr, "n = %d n1 = %d n2 = %d current = %d\n", 
  850.         n, text -> n1, text -> n2, text -> no_current_line );
  851. #endif DEBUG
  852.     
  853.     if ( n != NULL )
  854.         (void) MoveScrollBar ( dpy, text -> swin, CURRENT, n );
  855.     else
  856.         (void) MoveScrollBar ( dpy, text -> swin, FIRST, 0 );
  857.  
  858.     MCLEAR ( text -> stat, MESSAGE );
  859.     MCLEAR ( text -> stat, FIRSTPAGE );
  860.     MCLEAR ( text -> stat, LASTPAGE );
  861. }
  862.  
  863.  
  864. /*
  865. **    Function name : SetAndDisplayPage
  866. **
  867. **    Description : Met la table des lignes a jour,
  868. **        et affiche la page courante.
  869. **
  870. **    Input : Le text courant.
  871. **    Ouput :
  872. */
  873. void SetAndDisplayPage ( text )
  874.     Text *text;
  875. {
  876.     ClipOn ( text, NULL );
  877.     (void) SetLinesTable ( text );
  878.     RefreshPage ( text );
  879.     ClipOff ( text );
  880. }
  881.  
  882.  
  883. /*
  884. **    Function name : ScrollDownCont
  885. **
  886. **    Description : Scroll tant que le 'ButtonPress' est 
  887. **        maintenu. Le Texte defile vers le haut.
  888. **    Input : 
  889. **    Ouput :
  890. */
  891. void ScrollDownCont ( text )
  892.     Text *text;
  893. {
  894.        XEvent event;
  895.  
  896.        for (;;) {
  897.           if ( XCheckMaskEvent ( dpy,  ButtonReleaseMask, &event ) == True )
  898.                  break;
  899.           if ( text -> no_current_line == text -> lines_in_buf ) continue;
  900.               ScrollNLine ( 1, text );
  901.           (void) MoveScrollBar ( dpy, text -> swin, CURRENT,
  902.                  text -> no_current_line - text -> n1 - 1 );
  903.           XSync ( dpy, False );
  904.        }
  905. }
  906.  
  907.  
  908. /*
  909. **    Function name : ScrollUpCont
  910. **
  911. **    Description : Scroll tant que le 'ButtonPress' est
  912. **        maintenu. Le Texte defile vers le bas.
  913. **
  914. **    Input : Le text courant.
  915. **    Ouput :
  916. */
  917. void ScrollUpCont ( text )
  918. Text *text;
  919. {
  920.        XEvent event;
  921.  
  922.        for (;;) {
  923.           if ( XCheckMaskEvent ( dpy,  ButtonReleaseMask, &event ) == True )
  924.                  break;
  925.           if ( (text -> no_current_line - text -> n1) == 1 ) {
  926.              (void) MoveScrollBar ( dpy, text -> swin, FIRST, 0 );
  927.              continue;
  928.           }
  929.           ScrollNLine ( -1, text );
  930.           (void) MoveScrollBar ( dpy, text -> swin, CURRENT,
  931.                  text -> no_current_line - text -> n1 - 1 );
  932.           XSync ( dpy, False );
  933.        }
  934. }
  935.  
  936.  
  937. /*
  938. **    Function name : klaxon
  939. **
  940. **    Description : 
  941. **    Input : 
  942. **    Ouput :
  943. */
  944. klaxon ()
  945. {
  946.        XBell ( dpy, 5 );
  947. }
  948.